// Learn TypeScript:
//  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html

const {ccclass, property} = cc._decorator;

// 本目录的
import Notifications from "./Notifications";

import SimulationManager from "../base/lockStep/SimulationManager";
import Simulation from "../base/lockStep/Simulation";
import EntityWorld from "../base/ECSR/EntityWorld";
import NotifyMgr, {SelfNotification} from "../base/notify/NotifyMgr";
import GameClientData from "./data/GameClientData";

// behaviour
import InputBehaviour from "./behaviours/InputBehaviour";
import EntityBehaviour from "../base/lockStep/behaviours/EntityBehaviour";

// system
// import MoveSystem from "./system/MoveSystem";

// component
import MapComponent from "./components/MapComponent";
import BubbleComponent from "./components/BubbleComponent";
import TransformComponent from "../base/ECSR/components/TransformComponent";

import Guid from "../../common/utils/Guid"
import BubbleUtil from "./BubbleUtil"
import ReadBubbleSystem from "./systems/ReadBubbleSystem";
import FindPathSystem from "./systems/FindPathSystem";
import MovePathSystem from "./systems/MovePathSystem";
import MapUtil from "./utilities/MapUtil";
import RemoveEntitySystem from "./systems/RemoveEntitySystem";
import AddBubbleToMapSystem from "./systems/AddBubbleToMapSystem";
import TimeUtil from "../../common/utils/TimeUtil";


@ccclass
export default class GameMain extends cc.Component {
    @property(cc.Node)
    FXLayer:cc.Node = null;

    isStart = false;
    // 逻辑world
    world:EntityWorld = null;


    Reset()
    {
        GameClientData.simId = "";
        this.world = null;
        SimulationManager.Instance().Reset();
        this.isStart = false;
    }

    StartGame()
    {
        cc.log("GameMain|StartGame");
        this.Reset();

        let simId = Guid.guid();
        cc.log("GameMain|StartGame| client simId=" + simId);
        GameClientData.simId = simId;

        let sim = new Simulation(simId);
        this.world = sim.GetEntityWorld();

        let entityBeh = new EntityBehaviour(sim);
        // 注意添加system的顺序
        entityBeh.AddSystem(new ReadBubbleSystem(this.world));
        entityBeh.AddSystem(new FindPathSystem(this.world));
        entityBeh.AddSystem(new MovePathSystem(this.world));
        entityBeh.AddSystem(new AddBubbleToMapSystem(this.world));
        entityBeh.AddSystem(new RemoveEntitySystem(this.world));

        // 注意添加behaviour的顺序
        sim.AddBehaviour(new InputBehaviour(sim));
        sim.AddBehaviour(entityBeh);

        cc.log("Main|StartGame|behavirous length=" + sim.behaviours.length)

        SimulationManager.Instance().AddSimulation(sim);

        SimulationManager.Instance().Start();
        this.isStart = true;
    }

    LoadMap(levelData: Object)
    {
        GameClientData.mapId = Guid.guid();
        let mapEntity = this.world.AddEntity(GameClientData.mapId);
        let mapComponent = new MapComponent();

        let bubbles = levelData["g"];

        for(let i = 0; i < bubbles.length; ++i)
        {
            let item = bubbles[i];
            if(item["b"][0]["id"] !== 0)
            {
                continue;
            }

            let bubbleItemId = Guid.guid();
            let bubbleEntity = this.world.AddEntity(bubbleItemId);
            var bubbleCom = new BubbleComponent();
            // let transCom = new TransformComponent(BubbleUtil.getPosByRowAndCol(i,j, _bubbleMap.length));
            let transCom = new TransformComponent(cc.Vec2.ZERO);

            bubbleCom.colorType = item["b"][0]["p"]["c"];
            bubbleCom.row = item["p"][1];
            bubbleCom.col = item["p"][0];

            bubbleEntity.AddComponent(transCom);
            bubbleEntity.AddComponent(bubbleCom);

            MapUtil.MapAddBall(bubbleItemId, bubbleCom.row, bubbleCom.col, mapComponent.bubbleMap);
        }

        cc.log("GameMain|LoadMap|bubbleLength=" + mapComponent.bubbleMap.length);

        mapEntity.AddComponent(mapComponent);

        // update transform position
        let me = this;
        for(let i = 0; i < mapComponent.bubbleMap.length; ++i)
        {
            let bubbleVec = mapComponent.bubbleMap[i];
            bubbleVec.forEach((itemId)=>{
                if(itemId !== null)
                {
                    let transCom = me.world.GetComponentByEntityId(itemId, "TransformComponent") as TransformComponent;
                    let bubbleCom = me.world.GetComponentByEntityId(itemId, "BubbleComponent") as BubbleComponent;
                    transCom.position = BubbleUtil.getPosByRowAndCol(bubbleCom.row, bubbleCom.col, mapComponent.bubbleMap.length);
                }
            });
        }
        // init mapCom position
        let diameter = 65.4;
        let height = (mapComponent.bubbleMap.length - 1) * diameter * Math.sin(Math.PI/3);
        mapComponent.height = height;
        if(height < 640)
        {
            let delta = 640 - height;
            mapComponent.position.y += delta;
        }
    
        NotifyMgr.Instance().Send(Notifications.LoadMap, new SelfNotification("", [mapComponent], this));
    }
    // LIFE-CYCLE CALLBACKS:

    onLoad () {
        this.StartGame();
        let me = this;
        cc.resources.load('leveldata/main/level1', function (err, jsonAsset: cc.JsonAsset) {
            me.LoadMap(jsonAsset.json);
        });
    }

    start () {
    }

    update (dt) 
    {
        if(this.isStart)
        {
            let t1 = TimeUtil.GetCurrTimeMs();
            SimulationManager.Instance().Run(dt);
            let t2 = TimeUtil.GetCurrTimeMs();
            cc.log("GameMain|cost=" + (t2 - t2));
        }
    }
}
